using System;
using System.ComponentModel;
using System.Threading;

namespace GeneralDFS.BusinessLogical.RemoteObject
{
    public partial class NameNodeRemoteObject
    {
        private int m_NextFingerToUpdate = 0;

        /// <summary>
        /// Update the local node's finger table entries on a background thread.
        /// </summary>
        /// <param name="sender">The background worker thread this task is running on.</param>
        /// <param name="ea">Args (ignored).</param>
        private void UpdateFingerTable(object sender, DoWorkEventArgs ea)
        {
            var me = (BackgroundWorker)sender;

            while (!me.CancellationPending)
            {
                try
                {
                    // update the fingers moving outwards - once the last finger
                    // has been reached, start again closest to LocalNode (0).
                    if (this.m_NextFingerToUpdate >= this._fingerTable.Length)
                    {
                        this.m_NextFingerToUpdate = 0;
                    }

                    try
                    {
                        // Node validity is checked by findSuccessor
                        this.FingerTable.Successors[this.m_NextFingerToUpdate] = FindSuccessor(this.FingerTable.StartValues[this.m_NextFingerToUpdate]);
                    }
                    catch (Exception e)
                    {
                        LogUtil.LogInfo("Unable to update Successor for start value {0} ({1}).", this.FingerTable.StartValues[this.m_NextFingerToUpdate], e.Message);
                    }

                    this.m_NextFingerToUpdate = this.m_NextFingerToUpdate + 1;
                }
                catch (Exception e)
                {
                    // (overly safe here)
                    LogUtil.LogInfo("Error occured during UpdateFingerTable ({0})", e.Message);
                }

                // TODO: make this configurable via config file or passed in as an argument
                Thread.Sleep(100);
            }
        }
    }
}
